﻿namespace Reap.AzureResource.Data.Infrastructure
{
	using System;
	using System.Collections.Generic;
	using System.Data.Entity;
	using System.Linq;
	using System.Linq.Expressions;

	using Reap.AzureResource.Model.Models;

	public class RespositoryBase<T>
		where T : class, new()
	{
		#region Fields

		private readonly IDbSet<T> dbSet;

		private AzureResourceContext dbContext;

		#endregion

		#region Constructors and Destructors

		public RespositoryBase(IDatabaseFactory databaseFactory)
		{
			this.DatabaseFactory = databaseFactory;
			this.dbSet = this.DbContext.Set<T>();
		}

		#endregion

		#region Properties

		protected AzureResourceContext DbContext
		{
			get
			{
				return this.dbContext ?? (this.dbContext = this.DatabaseFactory.Get());
			}
		}

		private IDatabaseFactory DatabaseFactory { get; set; }

		#endregion

		#region Public Methods and Operators

		public virtual T Add(T entity)
		{
			this.dbSet.Add(entity);
			return entity;
		}

		public virtual void Delete(T entity)
		{
			this.dbSet.Remove(entity);
		}

		public virtual void Delete(Expression<Func<T, bool>> where)
		{
			IEnumerable<T> objects = this.dbSet.Where(where).AsEnumerable();
			foreach (T obj in objects)
			{
				this.dbSet.Remove(obj);
			}
		}

		public virtual IEnumerable<T> GetAll()
		{
			return this.dbSet.ToList();
		}

		public virtual T GetById(int id)
		{
			return this.dbSet.Find(id);
		}

		public virtual IEnumerable<T> GetMany(Expression<Func<T, bool>> where)
		{
			return this.dbSet.Where(where).ToList();
		}

		public virtual IQueryable<T> Query(Expression<Func<T, bool>> where)
		{
			return this.dbSet.Where(where);
		}

		public virtual void Update(T entity)
		{
			this.dbSet.Attach(entity);
			this.dbContext.Entry(entity).State = EntityState.Modified;
		}

		#endregion
	}
}